package top.z.orm.handle.osql.transaction;

import top.z.orm.core.osql.BeeSQLException;
import top.z.orm.core.osql.transaction.Transaction;
import top.z.orm.core.osql.transaction.TransactionIsolationLevel;
import top.z.orm.handle.osql.core.*;

import java.sql.Connection;
import java.sql.SQLException;

public class JdbcTransaction implements Transaction {

    private Connection conn    = null;
    private boolean    oldAutoCommit;
    private boolean    isBegin = false;

    private Connection initOneConn() {
        return SessionFactory.getConnection();
    }

    @Override
    public void begin() {
        try {
            this.conn = initOneConn();
            setOldAutoCommit(conn.getAutoCommit());
            conn.setAutoCommit(false);
            //存入上下文
            HoneyContext.setCurrentConnection(this.conn);
            isBegin = true;
        } catch (SQLException e) {
            throw ExceptionHelper.convert(e);
        }
    }

    @Override
    public void commit() {
        if (!isBegin) throw new BeeSQLException("The Transaction did not to begin!");
        try {
            if (conn != null && !conn.getAutoCommit()) {
                conn.commit();
                if (oldAutoCommit != conn.getAutoCommit()) conn.setAutoCommit(oldAutoCommit);
            }
        } catch (SQLException e) {
            throw ExceptionHelper.convert(e);
        } finally {
            _close();
            isBegin = false;
        }
    }

    @Override
    public void rollback() {
        try {
            if (conn != null && !conn.getAutoCommit()) {
                conn.rollback();
                if (oldAutoCommit != conn.getAutoCommit()) conn.setAutoCommit(oldAutoCommit);
            }
        } catch (SQLException e) {
            throw ExceptionHelper.convert(e);
        } finally {
            _close();
        }
    }

    @Override
    public void setReadOnly(boolean readOnly) {
        try {
            conn.setReadOnly(readOnly);
        } catch (SQLException e) {
            throw ExceptionHelper.convert(e);
        }
    }

    @Override
    public void setTransactionIsolation(TransactionIsolationLevel transactionIsolationLevel) {
        try {
            conn.setTransactionIsolation(transactionIsolationLevel.getLevel());
        } catch (SQLException e) {
            throw ExceptionHelper.convert(e);
        }
    }

    @Override
    public boolean isReadOnly() {
        try {
            return conn.isReadOnly();
        } catch (SQLException e) {
            throw ExceptionHelper.convert(e);
        }
    }

    @Override
    public int getTransactionIsolation() {
        try {
            return conn.getTransactionIsolation();
        } catch (SQLException e) {
            throw ExceptionHelper.convert(e);
        }
    }

    @Override
    public void setTimeout(int second) {
        //todo
        Logger.error("Do not support setTimeout(int second) in JdbcTransaction");
    }

    private void setOldAutoCommit(boolean oldAutoCommit) {
        this.oldAutoCommit = oldAutoCommit;
    }

    private void _close() {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw ExceptionHelper.convert(e);
            } finally {
                //事务结束时要删除
                HoneyContext.removeCurrentConnection();
                boolean enableMultiDs = HoneyConfig.getHoneyConfig().enableMultiDs;
                int     multiDsType   = HoneyConfig.getHoneyConfig().multiDsType;
                if (enableMultiDs && multiDsType == 2) {
                    //仅分库,有多个数据源时
                    HoneyContext.removeCurrentRoute();
                }
            }
        }
    }
}